home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / IrComm Remote / DVDRemote / Hack / zzOther / Hack68k / SerDemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-20  |  19.6 KB  |  846 lines  |  [TEXT/MPS ]

  1.  
  2. #include    <Types.h>
  3. //#include    <SysEqu.h>
  4. #include    <Resources.h>
  5. #include    <QuickDraw.h>
  6. #include    <Fonts.h>
  7. #include    <Events.h>
  8. #include    <Menus.h>
  9. #include    <Controls.h>
  10. #include    <Dialogs.h>
  11. #include    <Memory.h>
  12. #include    <Files.h>
  13. #include    <Devices.h>
  14. #include    <Serial.h>
  15. #include    <Timer.h>
  16. #include    <OSUtils.h>
  17. #include    <Processes.h>
  18. #include    <Gestalt.h>
  19. #include    <Errors.h>
  20. #include    <string.h>
  21. #include    <Speech.h>
  22.  
  23.  
  24. #define        rMonitor        1000
  25. #define        kSendButton        1
  26. #define        kStopButton        2
  27. #define        kQuitButton        3
  28. #define        kMsgBox            4
  29. #define        kSendSpinner    5
  30. #define        kRcvSpinner        7
  31. #define        kHoldFlag        9
  32. #define        kBreakButton    10
  33.  
  34. #define        rSerDataRsrc    128
  35. #define        rSpinnerIcon    1000
  36. #define        rHeldIcon        128
  37. #define        rNotHeldIcon    129
  38.  
  39. #define        rPortOpenALRT    256
  40. #define        kReset            2
  41.  
  42. #define        kCtlEnable        0
  43. #define        kCtlDisable        255
  44. #define        kSerBufSize        16384
  45. #define        kSerRdSize        64
  46. #define        kSerConfig        baud9600 + noParity + data8 + stop10
  47. #define        kBreakLength    666                // serial break length in milliseconds 
  48.  
  49. #define drvrName 0x12                // offset to driver name in 'DRVR' std. header 
  50.  
  51. #define dOpened  5
  52. #define dRAMBased  6
  53. #define drvrActive  7            // Device Manager DCtlFlag bits 
  54.                 
  55. #define kSerStatus  8
  56. #define kSerClrBrk  11            // Serial Driver csCodes 
  57. #define kSerSetBrk  12
  58. #define kSerHShakeDTR  14
  59. #define breakR0  128                // mask for break bit in SCC RR0 -- See TN #56 
  60. #define breakErr  8                    // mask for break bit in cumErrs -- System 7.0 
  61.  
  62. #define kDVDName "\pApple DVD Player"
  63. #define kCDName "\pAppleCD Audio Player"
  64.  
  65. /*
  66. typedef struct {
  67.     IOParam        fIOParam;
  68.     long        appA5;
  69. } ExtIOParam;
  70.  
  71. typedef struct {
  72.     TMTask        fTMTask;
  73.     long        appA5;
  74. } ExtTMTask;
  75.  
  76. typedef struct {
  77.     unsigned char    readR0;
  78.     unsigned char    deltaBits;
  79.     short            drvrPosting;
  80. } SERDEventMessage;
  81. */
  82.  
  83.  
  84. //Boolean        gHeldOff,
  85. //            gAllDone = false,
  86. //            gShouldSend = false,
  87. //            gReload = false,
  88. //            gKillBreak = false,
  89. //            gBreakReceived = false;
  90.  
  91. Ptr            gpSerBuf, *ghSerBuf,            // serial receive buffer
  92.             gpOutputData, *ghOutputData,    // send buffer
  93.             gpBitBucket, *ghBitBucket;        // receive processing buffer
  94.  
  95. long        gOutputDataSize;
  96. IOParam        *gpSendPB, **ghSendPB;        // for PBWrite calls to send data
  97. short        gSysVersion,
  98.             gOutRefNum, gInRefNum,
  99. //            gSendCount = 0,
  100.             gBitBucketCount = 0;
  101. //char        *panicString = "Help! I'm stuffed! And here's a bunch of characters to prove it!\n\r";
  102. TMTask        gPostEventTask;
  103.  
  104.  
  105.  
  106. short    Initialize (void);
  107. void    CleanUp (void);
  108. Boolean    OpenSERD (void);
  109. void    CloseSERD (void);
  110. void    DoIOStuff (void);
  111. OSErr    SendData (void);
  112. void    CheckSerData (long reqBytes);
  113. void    CheckSerStatus (void);
  114. pascal Boolean NullGrabber (DialogPtr, EventRecord *evt, short *itemHit);
  115. pascal void    SendCompRout (void);
  116. pascal void FlagBreakTimeout (void);
  117. void ProcessBitBucket(void);
  118. void PrimeTMTask(void);
  119. void PostPostEventProc(void);
  120. void TaskPtrData(void);
  121. void ProcessString(unsigned char* s);
  122.  
  123. //pascal void PostEventProc (TMTaskPtr task:__A1);
  124. #pragma parameter PostEventProc(__A1)
  125. void PostEventProc (TMTaskPtr taskP);
  126. //pascal void PostEventProc (void);
  127.  
  128. //OSErr    AssertDrvrOpen (Str255 name, short *refNum);
  129.  
  130. //ParmBlkPtr GetParmBlkPtr (void) = 0x2008;        // MOVE.L A0,D0 
  131. //TMTaskPtr GetTMTaskPtr (void) = 0x2009;            // MOVE.L A1,D0 
  132.  
  133. //#pragma parameter __D0 PBControlImmed(__A0)
  134. //pascal OSErr PBControlImmed(ParmBlkPtr paramBlock) = 0xA204;        // _Control ,IMMED 
  135.  
  136. //#pragma parameter __D0 PBStatusImmed(__A0)
  137. //pascal OSErr PBStatusImmed(ParmBlkPtr paramBlock) = 0xA205;            // _Status ,IMMED 
  138.  
  139.  
  140.  
  141. void main (void)
  142. {
  143.     InitGraf(&qd.thePort);
  144.     InitFonts();
  145.     InitWindows();
  146.     InitMenus();
  147.     InitDialogs(NULL);
  148.     InitCursor();
  149.  
  150. /*
  151.     {
  152.     ProcessSerialNumber psn;
  153.     ProcessInfoRec info;
  154.     OSErr err;
  155.     
  156.         
  157.     GetCurrentProcess(&psn);
  158.     err = GetProcessInformation(&psn, &info);
  159.     
  160.     if(err != noErr) DebugStr("\pcan't get process info");
  161.     DebugStr(info.processName);
  162.  
  163.     }
  164.     
  165. */    
  166.         
  167.     if (Initialize() == noErr) {
  168.         
  169.         if (OpenSERD()) {    // open the Serial Driver 
  170.             DoIOStuff();
  171.             CloseSERD();    // close the Serial Driver 
  172.         }
  173.         CleanUp();
  174.     }
  175.     
  176. }
  177.  
  178. //#define kInputDriver "\p.AIn"
  179. //#define kOutputDriver "\p.AOut"
  180. #define kInputDriver "\p.IrIn"
  181. #define kOutputDriver "\p.IrOut"
  182.  
  183.  
  184. Boolean OpenSERD (void)
  185. {
  186.     OSErr    openOutErr, openInErr;
  187.     OSErr    setBufErr, setCfgErr, setHskErr;
  188.     SerShk    hskFlags;
  189. //    long    finalTicks;
  190.     Boolean    takeOverPort = true;
  191. //    Boolean    openAOut, openAIn;
  192.     
  193. /*    openAOut = AssertDrvrOpen(kOutputDriver, &gOutRefNum) == noErr;
  194.     openAIn = AssertDrvrOpen(kInputDriver, &gInRefNum) == noErr;
  195.     if (openAOut || openAIn) {
  196.         if (takeOverPort = CautionAlert(rPortOpenALRT, nil) == kReset) {
  197.             if (openAIn) {
  198.                 KillIO(gInRefNum);
  199.                 CloseDriver(gInRefNum);
  200.             }
  201.             if (openAOut) {
  202.                 KillIO(gOutRefNum);
  203.                 CloseDriver(gOutRefNum);
  204.             }
  205.         }
  206.     }
  207.     
  208.     if (takeOverPort) {
  209. */
  210.         openOutErr = OpenDriver(kOutputDriver, &gOutRefNum);
  211.         openInErr = OpenDriver(kInputDriver, &gInRefNum);
  212.         
  213.         if (openOutErr == noErr && openInErr == noErr) {
  214.                     
  215.             // It's always good to first set a non-default input buffer, if desired. 
  216.             // There is no output buffering, so specify only the input driver.       
  217.             
  218.             setBufErr = SerSetBuf(gInRefNum, gpSerBuf, kSerBufSize);
  219.             
  220.             hskFlags.fXOn = false;
  221.             hskFlags.fCTS = true;
  222.             hskFlags.xOn = 0x11;
  223.             hskFlags.xOff = 0x13;
  224.             hskFlags.errs = 0;
  225.             
  226.             if (gSysVersion >= 0x0700) {
  227.                 hskFlags.evts = 0;                // I can use new means of break detection. 
  228.             }
  229.             else {
  230.                 hskFlags.evts = breakEvent;        // I need the driver to post break events. 
  231.             }
  232.             
  233.             hskFlags.fInX = false;
  234.             hskFlags.fDTR = true;
  235.             
  236.             // SerHShake() does not support full DTR/CTS hardware handshaking. You   
  237.             // accomplish the same thing and more with a Control call and csCode 14. 
  238.             // You only need to specify hskFlags once, to the output driver.         
  239.             
  240.             setHskErr = Control(gOutRefNum, kSerHShakeDTR, (Ptr) &hskFlags);
  241.  
  242.             // Now reset both input and output drivers with the same configuration.  
  243.             // Only a single call to the output driver is necessary to do this.      
  244.             // Differing concurrent input/output baud rates are not supported.       
  245.             
  246.             setCfgErr = SerReset(gOutRefNum, kSerConfig);
  247.             
  248.         }
  249.         else DebugStr("\pCan't open driver");
  250. //    }
  251.     
  252.     return takeOverPort;
  253. }
  254.  
  255.  
  256.  
  257. void CloseSERD (void)
  258. {
  259.     OSErr    killErr, closeOutErr, closeInErr;
  260.  
  261.     killErr = KillIO(gInRefNum);
  262.     closeInErr = CloseDriver(gInRefNum);
  263.  
  264.     killErr = KillIO(gOutRefNum);
  265.     closeOutErr = CloseDriver(gOutRefNum);
  266.  
  267. }
  268.  
  269.         
  270.  
  271.  
  272. void CheckSerData (long /*reqBytes*/)
  273. {
  274.     OSErr    checkBufErr, serRdErr;
  275.     long    charCount;
  276.     
  277.     // long    finalTicks;
  278.     // register long overrun;
  279.     
  280.     checkBufErr = SerGetBuf(gInRefNum, &charCount);
  281.     if (checkBufErr == noErr) {
  282.     
  283.         // The general strategy here is this: if number of available characters 
  284.         // meets a certain minimum threshold, then I read in everything in the  
  285.         // buffer. If I get delayed, I'll catch up quickly.                     
  286.  
  287. //        if (charCount != 0 && charCount >= reqBytes) {
  288.         if (charCount > 0) {
  289.             
  290.             serRdErr = FSRead(gInRefNum, &charCount, &gpBitBucket[gBitBucketCount]);
  291.             if (serRdErr == noErr) {
  292.                 gBitBucketCount += charCount;
  293.                 gpBitBucket[gBitBucketCount] = 0xFF; // append an 'unfinished string' terminator
  294. //                DebugStr("\pgotsome!");
  295.             }
  296.         }
  297.     }
  298. }
  299.  
  300.  
  301.  
  302. void DoIOStuff (void)
  303. {
  304. //    DialogPtr        serMonitor;
  305. //    OSErr            primeErr;
  306. //    short            itemHit, itemType;
  307. //    ControlHandle    sendItem, stopItem, breakItem;
  308. //    Handle            spinner, flag, item;
  309. //    Rect            box;
  310. //    CntrlParam        breakPB;
  311.     
  312. //    serMonitor = GetNewDialog(rMonitor, NULL, NULL);
  313. //    SetPort((GrafPtr) serMonitor);
  314.     
  315.     // send some data
  316.     SendData();
  317.     
  318. //    PrimeTMTask();
  319.     
  320.     while(!Button())
  321.     {
  322.         EventRecord theEvent;
  323.         CheckSerData(4);
  324.         WaitNextEvent(everyEvent, &theEvent, 10, 0);
  325.         
  326.         ProcessBitBucket();
  327.         
  328. /*        if(gRcvCount >= 4)
  329.         {
  330.             gpBitBucket[5] = 0;
  331.             c2pstr(gpBitBucket);
  332.             DebugStr((unsigned char*)gpBitBucket);
  333.         }
  334. */
  335.     }
  336.         
  337. }
  338.  
  339.  
  340. void ProcessBitBucket(void)
  341. {
  342.     char* s = gpBitBucket;
  343.     short i = 0;
  344.     Boolean foundString = false;
  345.     
  346.     while(foundString == false && i < gBitBucketCount)
  347.     {
  348.         if(s[i] == '\r')
  349.         {
  350.             foundString = true;
  351.             s[i] = 0; // null terminate the string
  352.         }
  353.         if(s[i] == 0xFF)
  354.         {
  355.             foundString = false;
  356.             break;
  357.         }
  358.         
  359.         i++;
  360.     }
  361.     
  362.     if(foundString == true) 
  363.     {
  364.         c2pstr(s);
  365.         SpeakString((unsigned char*)s);
  366.         
  367.         ProcessString((unsigned char*)s);
  368.         
  369.         gBitBucketCount -= i;
  370.         BlockMove(&s[i], &s[0], gBitBucketCount);
  371.     }
  372.     
  373.     return;
  374. }
  375.  
  376. void ProcessString(unsigned char* s)
  377. {
  378.     if(EqualString(s, "\pPlay", false, false))
  379.     {
  380.         PostEvent(keyDown, ' ');
  381.     }
  382.     else if(EqualString(s, "\pPause", false, false))
  383.     {
  384.         PostEvent(keyDown, ' ');
  385.     }
  386.     else if(EqualString(s, "\pStop", false, false))
  387.     {
  388.         
  389.     }
  390.     else if(EqualString(s, "\pFast Forward", false, false))
  391.     {
  392.         
  393.     }
  394.     else if(EqualString(s, "\pRewind", false, false))
  395.     {
  396.         
  397.     }
  398.     
  399.     return;
  400. }
  401.  
  402. OSErr SendData (void)
  403. //short SendData (void)
  404. {
  405.     gpSendPB->ioCompletion = 0;//(ProcPtr)0;// SendCompRout;
  406.     gpSendPB->ioRefNum = gOutRefNum;
  407.     gpSendPB->ioBuffer = gpOutputData;
  408.     gpSendPB->ioReqCount = gOutputDataSize;
  409. //    ((ExtIOParam *) gpSendPB)->appA5 = SetCurrentA5();    // completion routine needs A5 
  410. //    gReload = true;
  411.     
  412. //    return PBWriteAsync((ParmBlkPtr) gpSendPB);            // asynchronous self-sustaining sends 
  413.     return PBWriteSync((ParmBlkPtr) gpSendPB);            // asynchronous self-sustaining sends 
  414.  
  415. }
  416.  
  417.  
  418.  
  419. short Initialize (void)
  420. {
  421.     long    result;
  422.     OSErr    gestErr;
  423.     
  424.     gestErr = Gestalt(gestaltSystemVersion, &result);
  425.     gSysVersion = result;
  426.     
  427.     ghSendPB = (IOParam **) NewHandle( sizeof(IOParam));
  428.     if (ghSendPB != NULL) {
  429.         MoveHHi((Handle) ghSendPB);
  430.         HLock((Handle) ghSendPB);
  431.         gpSendPB = *ghSendPB;
  432.     }
  433.     else {
  434.         return MemError();
  435.     }
  436.  
  437.     ghSerBuf = NewHandle(kSerBufSize);
  438.     if (ghSerBuf != NULL) {
  439.         MoveHHi((Handle) ghSerBuf);
  440.         HLock((Handle) ghSerBuf);
  441.         gpSerBuf = *ghSerBuf;
  442.     }
  443.     else {
  444.         DisposeHandle((Handle) ghSendPB);
  445.         return MemError();
  446.     }
  447.     
  448.     ghBitBucket = NewHandle(kSerBufSize);
  449.     if (ghBitBucket != NULL) {
  450.         MoveHHi(ghBitBucket);
  451.         HLock(ghBitBucket);
  452.         gpBitBucket = *ghBitBucket;
  453.     }
  454.     else {
  455.         DisposeHandle((Handle) ghSendPB);
  456.         DisposeHandle((Handle) ghSerBuf);
  457.         return MemError();
  458.     }
  459.     
  460.     ghOutputData = Get1Resource('sDAT', rSerDataRsrc);
  461.     if (ghOutputData != NULL) {
  462.         MoveHHi(ghOutputData);
  463.         HLock(ghOutputData);
  464.         gpOutputData = *ghOutputData;
  465.         gOutputDataSize = GetResourceSizeOnDisk(ghOutputData);
  466.     }
  467.     else {
  468.         DisposeHandle((Handle) ghSendPB);
  469.         DisposeHandle((Handle) ghSerBuf);
  470.         DisposeHandle(ghBitBucket);
  471.         return ResError();
  472.     }
  473.     
  474. /*    // I use a Time Manager task to time breaks. This is where I install it.
  475.     
  476.     gUnBreakTask.fTMTask.tmAddr = FlagBreakTimeout;
  477.     gUnBreakTask.appA5 = SetCurrentA5();
  478.     InsTime((QElemPtr) &gUnBreakTask);
  479. */
  480.     {
  481.     TimerUPP upp = NewTimerProc(PostEventProc);
  482.     
  483. //    gPostEventTask.tmAddr = (TimerUPP)PostEventProc;
  484.     gPostEventTask.tmAddr = upp;
  485.     gPostEventTask.tmWakeUp = 0;
  486.     gPostEventTask.tmReserved = 0;
  487. //    gPostEventTask.appA5 = SetCurrentA5();
  488.     InsTime((QElemPtr) &gPostEventTask);
  489.     }
  490.     
  491.     return noErr;
  492. }
  493.  
  494. void PrimeTMTask(void)
  495. {
  496.     
  497.     PrimeTime((QElemPtr) &gPostEventTask,2000);
  498.     
  499.     return;
  500. }
  501.  
  502.  
  503. //pascal void PostEventProc (TMTaskPtr task:__A1)
  504. void PostEventProc (TMTaskPtr taskP:__A1)
  505. {
  506. //    long    oldA5;
  507.     OSErr err;
  508.     unsigned char* curAppName = (unsigned char*)0x00000910;
  509.     
  510.     
  511.     if(EqualString(curAppName, kCDName, false, false))
  512.     {
  513.         DebugStr(curAppName);
  514.         err = PostEvent(keyDown, ' ');
  515.         if(err != 0) DebugStr("\pCan't post event");
  516.     }
  517.     else
  518.     {
  519.         PrimeTime((QElemPtr) taskP, 100);
  520.     }
  521.     
  522. }
  523. /*    
  524.     if(info.processType == 'APPL' && info.processSignature == kCDCreator)
  525.     {
  526. //        err = PostEvent(keyDown, ' ');
  527.         DebugStr("\pGot it!!!;g");
  528.     }
  529.     else
  530.     {
  531. //        taskP->tmWakeUp = 0;
  532. //        taskP->tmReserved = 0;
  533. //        PrimeTime((QElemPtr) taskP, 2000);
  534.     }
  535.     
  536. //    oldA5 = SetA5(((ExtTMTask *) GetTMTaskPtr())->appA5);        // retrieve A5 
  537.     
  538. //    gKillBreak = true;
  539.     
  540. //    SetA5(oldA5);
  541.     */
  542.     
  543. /*
  544.     ProcessSerialNumber psn;
  545.     ProcessInfoRec info;
  546.     OSErr err;
  547.     Debugger();
  548.     
  549.     err = GetCurrentProcess(&psn);
  550.     if(err != noErr) DebugStr("\pCan't get current process");
  551.     else
  552.     {
  553.         err = GetProcessInformation(&psn, &info);
  554.         
  555.         if(err != noErr) DebugStr("\pcan't get process info");
  556.         else DebugStr(info.processAppSpec->name);
  557.     }
  558. */
  559.  
  560. /*
  561. asm void TaskPtrData(void)
  562. {
  563.     dc.l kReplaceEmToken
  564. }
  565.  
  566. // just a marker so that we can copy this proc into RAM & modify it.
  567. void PostPostEventProc(void)
  568. {}
  569. */
  570.  
  571. void CleanUp (void)
  572. {
  573.     // I remove the Time Manager task before exiting. 
  574.     
  575.     RmvTime((QElemPtr) &gPostEventTask);
  576.  
  577.     DisposeHandle((Handle) ghSendPB);
  578.     DisposeHandle(ghSerBuf);
  579.     DisposeHandle(ghBitBucket);
  580. }
  581.  
  582.  
  583.  
  584. #pragma mark • Commented out
  585.  
  586.  
  587. /*
  588.     while (!gAllDone) {
  589.         
  590.             CheckSerStatus();
  591.         
  592.     
  593.             if (gShouldSend && gReload) {
  594.                 gSendCount++;                // increment a counter for the output spinner 
  595.                 gReload = !gReload;
  596.             }
  597.             
  598.         // The break timer simply sets a global flag which I use to indicate when  
  599.         // to clear a break condition. Again, I use an immediate Control call, but 
  600.         // primarily for consistency, and also to show off.                        
  601.             
  602.             if (gKillBreak) {
  603.                 breakPB.ioCRefNum = gOutRefNum;
  604.                 breakPB.csCode = kSerClrBrk;
  605.                 PBControlImmed((ParmBlkPtr) &breakPB);        // SerClrBrk(), but IMMED 
  606.                 gKillBreak = !gKillBreak;
  607.                 GetDialogItem(serMonitor, kBreakButton, &itemType, &(Handle) breakItem, &box);
  608.                 HiliteControl(breakItem, kCtlEnable);
  609.             }
  610.         
  611.         // If another area of the program detects a break, I flag the occurrence here. 
  612.         
  613.             if (gBreakReceived) {
  614.                 SysBeep(1);
  615.                 SysBeep(1);
  616.                 gBreakReceived = !gBreakReceived;
  617.             }
  618.  
  619.         
  620.         // In lieu of an event loop, I just use a modal dialog with a relatively  
  621.         // simple (but unusual) filterProc. This is not a good example of how to  
  622.         // write an app. Modal dialogs are evil and to be avoided if possible.    
  623.         // Nonetheless, the filterProc is an interesting example unto itself....  
  624.     
  625.             ModalDialog(NullGrabber, &itemHit);
  626.             switch (itemHit) {
  627.                 
  628.                 case kStopButton:
  629.                     if (gShouldSend) {
  630.                         gShouldSend = !gShouldSend;
  631.                     }
  632.                     break;
  633.                 
  634.                 case kSendButton:
  635.                     if (!gShouldSend) {
  636.                         gShouldSend = !gShouldSend;
  637.                         primeErr = SendData();
  638.                     }
  639.                     break;
  640.                 
  641.                 case kBreakButton:
  642.                 
  643.                 // In another possible Mac IIfx IOP bug, SerSetBrk() called synchronously  
  644.                 // appears to hang the machine if an async write is pending. Since that is 
  645.                 // often the case (at least in this application) I work around the problem 
  646.                 // by making the Control call immediate--this prevents the hang, but also  
  647.                 // raises another interesting issue about when break is actually asserted. 
  648.                 
  649.                     breakPB.ioCRefNum = gOutRefNum;
  650.                     breakPB.csCode = kSerSetBrk;
  651.                     PBControlImmed((ParmBlkPtr) &breakPB);        // SerSetBrk(), but IMMED 
  652.                     
  653.                 // With break asserted, I prime a Time Manager task to flag the end of    
  654.                 // the break, and disable the Break button so that it cannot be selected  
  655.                 // again until break is negated.                                          
  656.                 
  657.                     PrimeTime((QElemPtr) &gUnBreakTask, kBreakLength);
  658.                     GetDialogItem(serMonitor, kBreakButton, &itemType, &(Handle) breakItem, &box);
  659.                     HiliteControl(breakItem, kCtlDisable);
  660.                     break;
  661.                 
  662.                 case kQuitButton:
  663.                     gAllDone = true;
  664.                     break;
  665.                 
  666.             }
  667.     }
  668.     */
  669.     
  670. //    DisposeDialog(serMonitor);
  671.  
  672.  
  673. /*
  674. pascal void FlagBreakTimeout (void)
  675. {
  676.     long    oldA5;
  677.     
  678.     oldA5 = SetA5(((ExtTMTask *) GetTMTaskPtr())->appA5);        // retrieve A5 
  679.     
  680.     gKillBreak = true;
  681.     
  682.     SetA5(oldA5);
  683.     
  684. }
  685. */
  686.  
  687.  
  688. /*
  689. pascal Boolean NullGrabber (DialogPtr dPtr, EventRecord *evt, short *itemHit)
  690. {
  691.     EventRecord    driverEvent;
  692.     
  693.     // Without this filterProc, none of the animation works: 
  694.     
  695.     // In order to keep things rolling along even when there are no events    
  696.     // such as mouse clicks or keystrokes, I have to return true in response  
  697.     // to null events. This is unusual, but otherwise ModalDialog() "handles" 
  698.     // null events by eating them and waiting for something better. This is   
  699.     // bad if I need to turn the spinner or clear a break condition.          
  700.     
  701.     // Also, I check for driver events here in order to detect breaks. 
  702.     
  703.     if (GetNextEvent(driverMask, &driverEvent)) {
  704.         if ((*(SERDEventMessage *) &driverEvent.message).drvrPosting == gInRefNum) {
  705.             gBreakReceived = ((*(SERDEventMessage *) &driverEvent.message).readR0 & breakR0) != 0;
  706.         }
  707.     }
  708.     
  709.     if (evt->what == nullEvent) {
  710.         *itemHit = 0;
  711.         return true;
  712.     }
  713.     
  714.     else {
  715.         return false;
  716.     }
  717.     
  718. }*/
  719.  
  720. /*
  721.  
  722. pascal void SendCompRout (void)
  723. {
  724.     long    oldA5;
  725.     
  726.     oldA5 = SetA5(((ExtIOParam *) GetParmBlkPtr())->appA5);        // retrieve A5 
  727.     
  728.     if (gShouldSend && !gAllDone) {
  729.         gReload = true;
  730.         gpSendPB->ioCompletion = (ProcPtr) SendCompRout;
  731.         PBWriteAsync((ParmBlkPtr) gpSendPB);            // this is the self-sustaining part     
  732.     }
  733.     
  734.     SetA5(oldA5);
  735.     
  736. }
  737. */
  738.  
  739. /*
  740. OSErr AssertDrvrOpen (Str255 name, short *refNum)
  741. {
  742.     DCtlHandle    *pUTEntry;
  743.     Ptr            pDrvr;
  744.     OSErr        result = notOpenErr;        // assume not open 
  745.     short        unitNo;
  746.     char        *aDrvrName;
  747.     
  748.     // The point here is to determine whether a driver is open, given its name.  
  749.     // This allows one to check a driver to see if it's open without hard coding 
  750.     // its reference number. (Normally, the way to get the refNum is to open     
  751.     // the driver--but that defeats the whole purpose!)                          
  752.     // This is an extension of the code discussed in Tech Note #71.              
  753.     
  754.     *refNum = 0;
  755.     pUTEntry = *(DCtlHandle **) UTableBase;
  756.     for (unitNo = 0; unitNo < *(short *) UnitNtryCnt; unitNo++, pUTEntry++) {
  757.         if (*pUTEntry != nil && **pUTEntry != nil) {
  758.             if (((***pUTEntry).dCtlFlags & 1 << dRAMBased) != 0)
  759.                 pDrvr = *(Handle) (***pUTEntry).dCtlDriver;
  760.             else
  761.                 pDrvr = (***pUTEntry).dCtlDriver;
  762.             
  763.             if (pDrvr != nil) {
  764.                 aDrvrName = pDrvr + drvrName;
  765.                 if (memcmp(aDrvrName, name, 1 + name[0]) == 0) {
  766.                     // We found the one we're after. 
  767.                     *refNum = ~unitNo;
  768.                     if (((***pUTEntry).dCtlFlags & 1 << dOpened) != 0)
  769.                         result = noErr;
  770.                     break;
  771.                 }
  772.             }
  773.         }
  774.     }    
  775.     
  776.     return result;
  777. }
  778.  
  779. */
  780.  
  781.  
  782. /*
  783. void CheckSerStatus (void)
  784. {
  785.     OSErr        checkStatErr, panicErr;
  786.     IOParam        altSendPB, *pAltSendPB = &altSendPB;
  787.     CntrlParam    statPB;
  788.     SerStaRec    serStat;
  789.     
  790.     statPB.ioCRefNum = gInRefNum;
  791.     statPB.csCode = kSerStatus;
  792.     checkStatErr = PBStatusImmed((ParmBlkPtr) &statPB);
  793.     serStat =  *(SerStaRec *) &statPB.csParam;
  794.     
  795.     // I check to see if the remote system has told me to stop sending. 
  796.     
  797.     gHeldOff = (Boolean) serStat.ctsHold;
  798.     
  799.     // Check for errors. 
  800.     
  801.     if (serStat.cumErrs & swOverrunErr)
  802.         DebugStr("\pSoftware Overrun Error");
  803.     else if (serStat.cumErrs & parityErr)
  804.         DebugStr("\pParity Error");
  805.     else if (serStat.cumErrs & hwOverrunErr)
  806.         DebugStr("\pHardware Overrun Error");
  807.     else if (serStat.cumErrs & framingErr)
  808.         DebugStr("\pFraming Error");
  809.     
  810.     // If I have System 7.0 or better, I can check directly to see if   
  811.     // I've received a break. Usually I don't check for a feature this  
  812.     // way, but in this case I have no alternative.                     
  813.     
  814.     if (gSysVersion >= 0x0700) {
  815.         gBreakReceived = (serStat.cumErrs & breakErr) != 0;
  816.     }
  817.     
  818.     // All I do here is send a small "panic" packet of characters back  
  819.     // to the remote system when it fills _my_ buffer. I don't actually 
  820.     // know the exact state of my buffer, but I can see if I've told    
  821.     // the remote system to shut up, indicating that I'm mostly full.   
  822.     
  823.     if (checkStatErr == noErr) {
  824.         if (( (unsigned char) serStat.xOffSent & dtrNegated) != 0) {
  825.             pAltSendPB->ioCompletion = NULL;
  826.             pAltSendPB->ioRefNum = gOutRefNum;
  827.             pAltSendPB->ioBuffer = panicString;
  828.             pAltSendPB->ioReqCount = strlen(panicString);
  829.             PBWriteAsync((ParmBlkPtr) pAltSendPB);
  830.             
  831.             // The program may hang here if the user quits the    
  832.             // remote application first--that could hold off our  
  833.             // serial output, leaving a pending asynchronous I/O  
  834.             // request and keeping us in an infinite loop.        
  835.             
  836.             while (pAltSendPB->ioResult > 0) {}                // I'll fix it later. 
  837.             // The reason I do this instead of just calling it synchronously 
  838.             // is so that if I do hang, I'll hang in my code for an obvious  
  839.             // reason instead of hanging up in the Device Manager.           
  840.             panicErr = pAltSendPB->ioResult;
  841.         }
  842.     }
  843.     
  844.     
  845. }
  846. */